{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "68d56705",
   "metadata": {},
   "source": [
    "# 图片入门\n",
    "- 读取一张图片（使用```cv::imread ```）\n",
    "- 在 **opencv** 窗口展示一张图片（使用```cv::imshow```）\n",
    "- 将图片写入文件（使用```cv::imwrite```）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "18110d50",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2 as cv\n",
    "import sys\n",
    "\n",
    "img = cv.imread(cv.samples.findFile(\"picture/12345.png\"))\n",
    "\n",
    "if img is None:\n",
    "    sys.exit(\"Could not read the image.\")\n",
    "\n",
    "cv.imshow(\"Display window\", img)\n",
    "k = cv.waitKey(0)\n",
    "\n",
    "if k == ord(\"s\"):\n",
    "    cv.imwrite(\"123.png\", img)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d294477",
   "metadata": {},
   "source": [
    "``` cpp\n",
    "\n",
    "#include <opencv2/core.hpp>\n",
    "#include <opencv2/imgcodecs.hpp>\n",
    "#include <opencv2/highgui.hpp>\n",
    "\n",
    "#include <iostream>\n",
    "\n",
    "using namespace cv;\n",
    "\n",
    "int main()\n",
    "{\n",
    "    std::string image_path = samples::findFile(\"starry_night.jpg\");\n",
    "    Mat img = imread(image_path, IMREAD_COLOR);\n",
    "\n",
    "    if(img.empty())\n",
    "    {\n",
    "        std::cout << \"Could not read the image: \" << image_path << std::endl;\n",
    "        return 1;\n",
    "    }\n",
    "\n",
    "    imshow(\"Display window\", img);\n",
    "    int k = waitKey(0); // Wait for a keystroke in the window\n",
    "\n",
    "    if(k == 's')\n",
    "    {\n",
    "        imwrite(\"starry_night.png\", img);\n",
    "    }\n",
    "\n",
    "    return 0;\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f9dfdc9",
   "metadata": {},
   "source": [
    "- **core** ： 库的基本构件块 \n",
    "- **imgcodecs** : 提供在窗口读写的函数\n",
    "- **highgui** : 包含在窗口显示图片的函数\n",
    "- ***using namespace cv**:使用函数时可省略写名称空间\n",
    "- **imread()** : 第一个参数图片路径，第二个参数图片的格式，有一下几种\n",
    "  - **IMREAD_COLOR** :BGR 8-bit格式，默认格式\n",
    "  - **IMREAD_UNCHANGED** : 按原样加载图片（包括阿尔法通道（如果存在））\n",
    "  - **IMREAD_GRAYSCALE** : 加载图像为灰度图\n",
    "- **Mat** : 读取的图片将存储在**cv::Mat**对象中\n",
    "- 支持加载的图片格式：bmp、pbm、pgm、ppm、sr、ras、jpeg、tiff、png、openexr等等\n",
    "- **imshow()**：第一个参数为窗口名，第二个参数为**cv::Mat**对象\n",
    "- **waitkey()**：等待用户输入\n",
    "- **imwrite()**: 将**cv::Mat**对象重写入指定路径"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "087b00f3",
   "metadata": {},
   "source": [
    "# 视频入门\n",
    "- 学习读取视频，展示视频和保存视频\n",
    "- 学习从相机捕获视频并显示\n",
    "- 将学习如下函数：**cv.VideoCapture(),cv.VideoWriter()**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b28dbce9",
   "metadata": {},
   "source": [
    "## 从相机捕获视频"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "508eeefc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "480.0\n",
      "640.0\n",
      "240.0\n",
      "320.0\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "cap = cv.VideoCapture(0)\n",
    "if not cap.isOpened():\n",
    "    print(\"Cannot open camera\")\n",
    "    exit()\n",
    "print(cap.get(cv.CAP_PROP_FRAME_HEIGHT))\n",
    "print(cap.get(cv.CAP_PROP_FRAME_WIDTH))\n",
    "cap.set(cv.CAP_PROP_FRAME_WIDTH,320)\n",
    "cap.set(cv.CAP_PROP_FRAME_HEIGHT, 240)\n",
    "print(cap.get(cv.CAP_PROP_FRAME_HEIGHT))\n",
    "print(cap.get(cv.CAP_PROP_FRAME_WIDTH))\n",
    "while True:\n",
    "    # Capture frame-by-frame\n",
    "    ret, frame = cap.read()\n",
    "\n",
    "    # if frame is read correctly ret is True\n",
    "    if not ret:\n",
    "        print(\"Can't receive frame (stream end?). Exiting ...\")\n",
    "        break\n",
    "    # Our operations on the frame come here\n",
    "    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)\n",
    "    # Display the resulting frame\n",
    "    cv.imshow('frame', gray)\n",
    "    if cv.waitKey(1) == ord('q'):\n",
    "        break\n",
    "\n",
    "# When everything done, release the capture\n",
    "cap.release()\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2d5a6b7",
   "metadata": {},
   "source": [
    "## 从文件播放视频"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fd2e79a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Can't receive frame (stream end?). Exiting ...\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "cap = cv.VideoCapture('output.avi')\n",
    "\n",
    "while cap.isOpened():\n",
    "    ret, frame = cap.read()\n",
    "\n",
    "    # if frame is read correctly ret is True\n",
    "    if not ret:\n",
    "        print(\"Can't receive frame (stream end?). Exiting ...\")\n",
    "        break\n",
    "    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)\n",
    "\n",
    "    cv.imshow('frame', gray)\n",
    "    if cv.waitKey(1) == ord('q'):\n",
    "        break\n",
    "\n",
    "cap.release()\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c7d80ea",
   "metadata": {},
   "source": [
    "## 保存视频"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "483b2889",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "cap = cv.VideoCapture(0)\n",
    "\n",
    "# Define the codec and create VideoWriter object\n",
    "fourcc = cv.VideoWriter_fourcc(*'XVID')\n",
    "out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,  480))\n",
    "\n",
    "while cap.isOpened():\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        print(\"Can't receive frame (stream end?). Exiting ...\")\n",
    "        break\n",
    "    frame = cv.flip(frame, 0)\n",
    "\n",
    "    # write the flipped frame\n",
    "    out.write(frame)\n",
    "\n",
    "    cv.imshow('frame', frame)\n",
    "    if cv.waitKey(1) == ord('q'):\n",
    "        break\n",
    "\n",
    "# Release everything if job is finished\n",
    "cap.release()\n",
    "out.release()\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "481ecf4a",
   "metadata": {},
   "source": [
    "- FourCC is a 4-byte code used to specify the video codec. The list of available codes can be found in fourcc.org. It is platform dependent. The following codecs work fine for me.\n",
    "  - In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high size video. X264 gives very small size video)\n",
    "  - In Windows: DIVX (More to be tested and added)\n",
    "  - In OSX: MJPG (.mp4), DIVX (.avi), X264 (.mkv)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4890f9eb",
   "metadata": {},
   "source": [
    "# 画图函数\n",
    "- 学习用opencv画不同的几何形状\n",
    "- 学习这些函数： **cv.line(), cv.circle(),cv.rectangle(),cv.ellipse,cv.putText()**\n",
    "  \n",
    "在如上的函数中，你将看到如下相同的参数：\n",
    "  - img : The image where you want to draw the shapes\n",
    "  - color : Color of the shape. for BGR, pass it as a tuple, eg: (255,0,0) for blue. For grayscale, just pass the scalar value.\n",
    "  - thickness : Thickness of the line or circle etc. If -1 is passed for closed figures like circles, it will fill the shape. default thickness = 1\n",
    "  - lineType : Type of line, whether 8-connected, anti-aliased line etc. By default, it is 8-connected. cv.LINE_AA gives anti-aliased line which looks great for curves.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d99a83b5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Drawing Line\n",
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "# Create a black image\n",
    "img = np.zeros((512,512,3), np.uint8)\n",
    "\n",
    "# Draw a diagonal blue line with thickness of 5 px\n",
    "cv.line(img,(0,0),(511,511),(255,0,0),5)\n",
    "\n",
    "cv.rectangle(img,(384,0),(510,128),(0,255,0),3)\n",
    "\n",
    "cv.circle(img,(447,63), 63, (0,0,255), -1)\n",
    "\n",
    "cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)\n",
    "\n",
    "pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)\n",
    "pts = pts.reshape((-1,1,2))\n",
    "cv.polylines(img,[pts],True,(0,255,255))\n",
    "\n",
    "font = cv.FONT_HERSHEY_SIMPLEX\n",
    "cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)\n",
    "\n",
    "cv.imshow('Line-Rectangle-Circle-Ellipse-Polygon-Text', img)\n",
    "cv.waitKey(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c483863",
   "metadata": {},
   "source": [
    "# 鼠标做画笔"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5edafdfd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2 as cv\n",
    "import numpy as np\n",
    "events = [i for i in dir(cv) if 'EVENT' in i]\n",
    "print( events )\n",
    "\n",
    "# mouse callback function\n",
    "def draw_circle(event,x,y,flags,param):\n",
    "    if event == cv.EVENT_LBUTTONDBLCLK:\n",
    "        cv.circle(img,(x,y),100,(255,0,0),-1)\n",
    "\n",
    "# Create a black image, a window and bind the function to window\n",
    "img = np.zeros((512,512,3), np.uint8)\n",
    "cv.namedWindow('image')\n",
    "cv.setMouseCallback('image',draw_circle)\n",
    "\n",
    "while(1):\n",
    "    cv.imshow('image',img)\n",
    "    if cv.waitKey(20) & 0xFF == 27:\n",
    "        break\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "38d2f711",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "drawing = False # true if mouse is pressed\n",
    "mode = True # if True, draw rectangle. Press 'm' to toggle to curve\n",
    "ix,iy = -1,-1\n",
    "\n",
    "# mouse callback function\n",
    "def draw_circle(event,x,y,flags,param):\n",
    "    global ix,iy,drawing,mode\n",
    "\n",
    "    if event == cv.EVENT_LBUTTONDOWN:\n",
    "        drawing = True\n",
    "        ix,iy = x,y\n",
    "\n",
    "    elif event == cv.EVENT_MOUSEMOVE:\n",
    "        if drawing == True:\n",
    "            if mode == True:\n",
    "                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)\n",
    "            else:\n",
    "                cv.circle(img,(x,y),5,(0,0,255),-1)\n",
    "\n",
    "    elif event == cv.EVENT_LBUTTONUP:\n",
    "        drawing = False\n",
    "        if mode == True:\n",
    "            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)\n",
    "        else:\n",
    "            cv.circle(img,(x,y),5,(0,0,255),-1)\n",
    "            \n",
    "img = np.zeros((512,512,3), np.uint8)\n",
    "cv.namedWindow('image')\n",
    "cv.setMouseCallback('image',draw_circle)\n",
    "\n",
    "while(1):\n",
    "    cv.imshow('image',img)\n",
    "    k = cv.waitKey(1) & 0xFF\n",
    "    if k == ord('m'):\n",
    "        mode = not mode\n",
    "    elif k == 27:\n",
    "        break\n",
    "\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d037a81",
   "metadata": {},
   "source": [
    "# 轨迹栏作为调色板\n",
    "- 学习将轨迹栏绑定到OpenCv窗口\n",
    "- 学习这些函数：**cv.getTrackbarPos(), cv.createTrackbar()** \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "70ff43eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import cv2 as cv\n",
    "\n",
    "def nothing(x):\n",
    "    pass\n",
    "\n",
    "# Create a black image, a window\n",
    "img = np.zeros((300,512,3), np.uint8)\n",
    "cv.namedWindow('image')\n",
    "\n",
    "# create trackbars for color change\n",
    "cv.createTrackbar('R','image',0,255,nothing)\n",
    "\n",
    "cv.createTrackbar('G','image',0,255,nothing)\n",
    "cv.createTrackbar('B','image',0,255,nothing)\n",
    "\n",
    "# create switch for ON/OFF functionality\n",
    "switch = '0 : OFF \\n1 : ON'\n",
    "cv.createTrackbar(switch, 'image',0,1,nothing)\n",
    "\n",
    "while(1):\n",
    "    cv.imshow('image',img)\n",
    "    k = cv.waitKey(1) & 0xFF\n",
    "    if k == 27:\n",
    "        break\n",
    "\n",
    "    # get current positions of four trackbars\n",
    "    r = cv.getTrackbarPos('R','image')\n",
    "    g = cv.getTrackbarPos('G','image')\n",
    "    b = cv.getTrackbarPos('B','image')\n",
    "    s = cv.getTrackbarPos(switch,'image')\n",
    "\n",
    "    if s == 0:\n",
    "        img[:] = 0\n",
    "    else:\n",
    "        img[:] = [b,g,r]\n",
    "\n",
    "cv.destroyAllWindows()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "opencv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
